/*
* Copyright 2015-2017 JKOOL, LLC.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jkoolcloud.tnt4j.stream.jmx;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Properties;
import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.VirtualMachineDescriptor;
/**
* Running JVM attaching/connecting realated utility methods.
*
* @version $Revision: 1 $
*/
public class VMUtils {
/**
* Attaches to running JVMs process.
*
* @param vmDescr
* JVM descriptor: display name fragment or pid
* @param agentPath
* agent library path
* @param agentOptions
* agent options
* @throws Exception
* if any exception occurs while attaching to JVM
*
* @see #findVMs(String)
*/
public static void attachVM(String vmDescr, String agentPath, String agentOptions) throws Exception {
Collection<VirtualMachineDescriptor> descriptors = findVMs(vmDescr);
for (VirtualMachineDescriptor descriptor : descriptors) {
System.out.println("SamplingAgent.attach: attaching agent " + agentPath + " to " + descriptor + "");
VirtualMachine virtualMachine = VirtualMachine.attach(descriptor.id());
try {
System.out.println("SamplingAgent.attach: VM loading agent agent.path=" + agentPath + ", agent.options="
+ agentOptions);
virtualMachine.loadAgent(agentPath, agentOptions);
System.out.println("SamplingAgent.attach: attached and loaded...");
} finally {
virtualMachine.detach();
}
}
}
/**
* Resolves running JVM JMX server connection address string. JVM has to have defined agent property
* {@code "com.sun.management.jmxremote.localConnectorAddress"}.
*
* @param vmDescr
* JVM descriptor: display name fragment or pid
* @return resolved JVM connection address string
* @throws Exception
* if any exception occurs while retrieving JVM connection address
*
* @see #findVMs(String)
*/
public static String getVMConnAddress(String vmDescr) throws Exception {
VirtualMachineDescriptor descriptor = findVMs(vmDescr).get(0);
final VirtualMachine virtualMachine = VirtualMachine.attach(descriptor.id());
String connectorAddress;
try {
Properties props = virtualMachine.getAgentProperties();
connectorAddress = props.getProperty("com.sun.management.jmxremote.localConnectorAddress");
if (connectorAddress == null) {
throw new RuntimeException("JVM does not support JMX connection...");
}
} finally {
virtualMachine.detach();
}
return connectorAddress;
}
/**
* Finds running JVMs matching defined VM descriptor string cotaining JVM process PID or display name fragment.
*
* @param vmDescr
* JVM descriptor: display name fragment or pid
* @return list of found JVM descriptors
* @throws RuntimeException
* if no running JVM found
*/
public static List<VirtualMachineDescriptor> findVMs(String vmDescr) {
List<VirtualMachineDescriptor> runningVMsList = VirtualMachine.list();
List<VirtualMachineDescriptor> descriptors = new ArrayList<>(5);
for (VirtualMachineDescriptor rVM : runningVMsList) {
if ((rVM.displayName().contains(vmDescr)
&& !rVM.displayName().contains(SamplingAgent.class.getSimpleName()))
|| rVM.id().equalsIgnoreCase(vmDescr)) {
descriptors.add(rVM);
}
}
if (descriptors.isEmpty()) {
System.err.println("SamplingAgent: ----------- Available JVMs -----------");
for (VirtualMachineDescriptor vmD : runningVMsList) {
System.err.println("SamplingAgent: JVM.id=" + vmD.id() + ", name=" + vmD.displayName());
}
System.err.println("SamplingAgent: ---------------- END ----------------");
throw new RuntimeException("Java VM not found using provided descriptor: [" + vmDescr + "]");
}
return descriptors;
}
}